﻿/* ==============================================================================
*
*   Copyright (c) 2010, Pierre Favier
*   All rights reserved.
*
*   NTasking is free software: you can redistribute it and/or modify it
*   under the terms of the GNU General Public License as published by the
*   Free Software Foundation.
*
*   Redistribution and use in source and binary forms, with or without
*   modification, are permitted provided that the following conditions
*   are met:
*
*   -   Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*
*   -   Redistributions in binary form must reproduce the above
*       copyright notice, this list of conditions and the following
*       disclaimer in the documentation and/or other materials
*       provided with the distribution.
*
*   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
*   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
*   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
*   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
*   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
*   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
*   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
*   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*   SUCH DAMAGE.
*
* ============================================================================== */

using System;
using System.Reflection;
using NTasking.Internals;

namespace NTasking
{

    /// <summary>
    /// Define all the error codes, messages and exceptions
    /// </summary>
    public static class Errors
    {

        // TODO : Add RM clause for errors

        private static int _lastErrorCode;


        private static int NextErrorCode()
        {
            return ++_lastErrorCode;
        }


        internal static void FatalError(string error)
        {
            Tracer.Trace(error);
            Environment.FailFast(error);
        }


        #region InvalidOperationException error messages

        private const string ResultNotSetMsg = "Result is not set";

        internal static InvalidOperationException ResultNotSet()
        {
            return new InvalidOperationException(ResultNotSetMsg);
        }


        private const string TaskNameNotChangeableMsg = "Task {0}: Property Name can only be set once";

        internal static InvalidOperationException TaskNameNotChangeable(ITask task)
        {
            return new InvalidOperationException(String.Format(TaskNameNotChangeableMsg, task));
        }


        private const string IncorrectTaskStatusMsg = "Task {0}: Operation not allowed for task status {1}";

        internal static InvalidOperationException IncorrectTaskStatus(ITask task)
        {
            return new InvalidOperationException(String.Format(IncorrectTaskStatusMsg, task, task.TaskStatus));
        }


        private const string ThreadAbortNotAllowedMsg = "Using Thread.Abort() method is not allowed, use ITask.Abort() instead";

        internal static InvalidOperationException ThreadAbortNotAllowed()
        {
            return new InvalidOperationException(ThreadAbortNotAllowedMsg);
        }


        private const string TaskingConfigurationNotChangeableMsg = "The runtime settings can only be changed outside the top-level Block";

        internal static InvalidOperationException TaskingConfigurationNotChangeable()
        {
            return new InvalidOperationException(TaskingConfigurationNotChangeableMsg);
        }

        #endregion


        #region IndexOutOfRangeException error messages

        private const string MemberIndexOutOfRangeMsg = "Entry Family {0}: '{1}' is not a valid index value";

        internal static IndexOutOfRangeException MemberIndexOutOfRange(SynchronizedMethod family, object index)
        {
            return new IndexOutOfRangeException(string.Format(MemberIndexOutOfRangeMsg, index, family));
        }

        #endregion


        #region NullReferenceException error messages

        internal static NullReferenceException EntryIsNull()
        {
            return new NullReferenceException("entry");
        }


        private const string BodyIsNullMsg = "Task {0}: {1}'s accept body is null";

        internal static NullReferenceException BodyIsNull(IExecutable executable)
        {
            return new NullReferenceException(string.Format(BodyIsNullMsg, executable.Family.Owner, executable.Family));
        }


        private const string ProtectedBodyIsNullMsg = "Protected {0}: {1}'s body is null";

        internal static NullReferenceException ProtectedBodyIsNull(Protected prot, SynchronizedMethod method)
        {
            return new NullReferenceException(string.Format(ProtectedBodyIsNullMsg, prot, method));
        }


        private const string RequeuedCallIsNullMsg = "Synchronized Object {0}: entry is null in Requeue[WithAbort] statement";

        internal static NullReferenceException RequeuedCallIsNull(SynchronizedObject obj)
        {
            return new NullReferenceException(string.Format(RequeuedCallIsNullMsg, obj));
        }

        #endregion


        #region SyntaxError error messages

        private const string SelectAcceptCalledFromOutsideTaskMsg =
            "Task {0} : a method containing a select or accept statement has been called from a different Task {1}\n" +
            "To avoid this problem, make sure that any method which contains select or accept statements is either protected or private.";
        public static readonly int SelectAcceptCalledFromOutsideTaskError = NextErrorCode();

        internal static SyntaxError SelectAcceptCalledFromOutsideTask(ITask task, ITask caller)
        {
            return new SyntaxError(SelectAcceptCalledFromOutsideTaskError, string.Format(SelectAcceptCalledFromOutsideTaskMsg, task, caller));
        }


        private const string SelectNotAllowedInAbortablePartMsg = "Task {0}: select statements are not allowed in the abortable part of a selective call.";
        public static readonly int SelectNotAllowedInAbortablePartError = NextErrorCode();

        internal static SyntaxError SelectNotAllowedInAbortablePart(ITask task)
        {
            return new SyntaxError(SelectNotAllowedInAbortablePartError, string.Format(SelectNotAllowedInAbortablePartMsg, task));
        }


        private const string AcceptNotAllowedInAbortablePartMsg = "Task {0}: accept statements are not allowed in the abortable part of a selective call.";
        public static readonly int AcceptNotAllowedInAbortablePartError = NextErrorCode();

        internal static SyntaxError AcceptNotAllowedInAbortablePart(ITask task)
        {
            return new SyntaxError(AcceptNotAllowedInAbortablePartError, string.Format(AcceptNotAllowedInAbortablePartMsg, task));
        }


        private const string SynchronizedTypeMismatchMsg = "Synchronized method {0}.{1}: type {2} is not supported by the runtime.";
        public static readonly int SynchronizedTypeMismatchError = NextErrorCode();

        internal static SyntaxError SynchronizedTypeMismatch(PropertyInfo property)
        {
            return new SyntaxError(SynchronizedTypeMismatchError, string.Format(SynchronizedTypeMismatchMsg, property.DeclaringType, property.Name, property.PropertyType));
        }


        private const string ConflictingAttributeMsg = "Synchronized method {0}.{1}: conflicting attributes defined in class and implemented interfaces.";
        public static readonly int ConflictingAttributeError = NextErrorCode();

        internal static SyntaxError ConflictingAttribute(PropertyInfo property)
        {
            return new SyntaxError(ConflictingAttributeError, string.Format(ConflictingAttributeMsg, property.DeclaringType, property.Name));
        }


        private const string NoPropertySetterMsg = "Synchronized method {0}.{1}: a synchronized method must declare a private setter.";
        public static readonly int NoPropertySetterError = NextErrorCode();

        internal static SyntaxError NoPropertySetter(PropertyInfo property)
        {
            return new SyntaxError(NoPropertySetterError, string.Format(NoPropertySetterMsg, property.DeclaringType, property.Name));
        }


        private const string TaskEntrySetterIsNotPrivateMsg = "Synchronized method {0}.{1}: a synchronized method setter must be private.";
        public static readonly int TaskEntrySetterIsNotPrivateError = NextErrorCode();

        internal static SyntaxError TaskEntrySetterIsNotPrivate(PropertyInfo property)
        {
            return new SyntaxError(TaskEntrySetterIsNotPrivateError, string.Format(TaskEntrySetterIsNotPrivateMsg, property.DeclaringType, property.Name));
        }


        private const string ProcedureFunctionNotAllowedForFamilyMsg = "Synchronized method {0}.{1}: method families can't be marked with the [Procedure] or [Function] attribute.";
        public static readonly int ProcedureFunctionNotAllowedForFamilyError = NextErrorCode();

        internal static SyntaxError ProcedureFunctionNotAllowedForFamily(PropertyInfo property)
        {
            return new SyntaxError(ProcedureFunctionNotAllowedForFamilyError, string.Format(ProcedureFunctionNotAllowedForFamilyMsg, property.DeclaringType, property.Name));
        }


        private const string ProcedureFunctionNotAllowedInTaskMsg = "Synchronized method {0}.{1}: Task's synchronized methods can't be marked with the [Procedure] or [Function] attribute.";
        public static readonly int ProcedureFunctionNotAllowedInTaskError = NextErrorCode();

        internal static SyntaxError ProcedureFunctionNotAllowedInTask(PropertyInfo property)
        {
            return new SyntaxError(ProcedureFunctionNotAllowedInTaskError, string.Format(ProcedureFunctionNotAllowedInTaskMsg, property.DeclaringType, property.Name));
        }


        private const string UnitializedProtectedActionMsg = "Protected method {0} has not been initialized.";
        public static readonly int UnitializedProtectedActionError = NextErrorCode();

        internal static SyntaxError UnitializedProtectedAction(SynchronizedMethod call)
        {
            return new SyntaxError(UnitializedProtectedActionError, string.Format(UnitializedProtectedActionMsg, call));
        }


        private const string InvalidVoidFuncMsg = "Synchronized method {0}.{1}: only 'Func<...>' properties can be marked with the [Function] attribute.";
        public static readonly int InvalidVoidFuncError = NextErrorCode();

        internal static SyntaxError InvalidVoidFunc(PropertyInfo property)
        {
            return new SyntaxError(InvalidVoidFuncError, string.Format(InvalidVoidFuncMsg, property.DeclaringType, property.Name));
        }


        private const string DeclarationConflictsWithAttributeMsg = "Synchronized Method {0} : the method initialization conflicts with its associated [Function] or [Procedure] Attribute.";
        public static readonly int DeclarationConflictsWithAttributeError = NextErrorCode();

        internal static SyntaxError DeclarationConflictsWithAttribute(SynchronizedMethod method)
        {
            return new SyntaxError(DeclarationConflictsWithAttributeError, string.Format(DeclarationConflictsWithAttributeMsg, method));
        }


        private const string RequeueProfileMismatchMsg = "Call to {0} can't be requeued to {1} because the parameters & return profiles do not match.";
        public static readonly int RequeueProfileMismatchError = NextErrorCode();

        internal static SyntaxError RequeueProfileMismatch(MethodCall original, MethodCall requeue)
        {
            return new SyntaxError(RequeueProfileMismatchError, string.Format(RequeueProfileMismatchMsg, original.Target, requeue.Target));
        }


        private const string InvalidNestedAcceptMsg = "Task {0}: Nested accept of the same entry or entry family {1} is not allowed";
        public static readonly int InvalidNestedAcceptError = NextErrorCode();

        internal static SyntaxError InvalidNestedAccept(ITask task, SynchronizedMethod call)
        {
            return new SyntaxError(InvalidNestedAcceptError, string.Format(InvalidNestedAcceptMsg, task, call));
        }


        private const string InvalidReadWriteCallMsg = "Protected {0}: Call to read-write operation {1} not allowed within read-only operation {2}";
        public static readonly int InvalidReadWriteCallError = NextErrorCode();

        internal static SyntaxError InvalidReadWriteCall(Protected prot, SynchronizedMethod call, SynchronizedMethod from)
        {
            return new SyntaxError(InvalidReadWriteCallError, string.Format(InvalidReadWriteCallMsg, prot, call, from));
        }


        private const string AcceptBodyIsSynchronizedMsg = "Task {0}: The body of an accept statement can't be synchronized method {1}";
        public static readonly int AcceptBodyIsSynchronizedError = NextErrorCode();

        internal static SyntaxError AcceptBodyIsSynchronized(ITask task, SynchronizedMethod method)
        {
            return new SyntaxError(AcceptBodyIsSynchronizedError, string.Format(AcceptBodyIsSynchronizedMsg, task, method));
        }


        private const string AbortablePartIsNullMsg = "abortable is null in selective call";
        public static readonly int AbortablePartIsNullError = NextErrorCode();

        internal static SyntaxError AbortablePartIsNull()
        {
            return new SyntaxError(AbortablePartIsNullError, AbortablePartIsNullMsg);
        }


        private const string ElseAlternativeIsNullMsg = "esle alternative is null in selective call";
        public static readonly int ElseAlternativeIsNullError = NextErrorCode();

        internal static SyntaxError ElseAlternativeIsNull()
        {
            return new SyntaxError(ElseAlternativeIsNullError, ElseAlternativeIsNullMsg);
        }


        private const string AsynchronousCallIsNullMsg = "entry is null in asynchronous call";
        public static readonly int AsynchronousCallIsNullError = NextErrorCode();

        internal static SyntaxError AsynchronousCallIsNull()
        {
            return new SyntaxError(AsynchronousCallIsNullError, AsynchronousCallIsNullMsg);
        }


        private const string SelectiveCallIsNullMsg = "entry is null in selective call statement";
        public static readonly int SelectiveCallIsNullError = NextErrorCode();

        internal static SyntaxError SelectiveCallIsNull()
        {
            return new SyntaxError(SelectiveCallIsNullError, SelectiveCallIsNullMsg);
        }


        private const string SelectiveCallNotAnEntryMsg = "Selective call target {0} is not an entry/entry family";
        public static readonly int SelectiveCallNotAnEntryError = NextErrorCode();

        internal static SyntaxError SelectiveCallNotAnEntry(object call)
        {
            return new SyntaxError(SelectiveCallNotAnEntryError, string.Format(SelectiveCallNotAnEntryMsg, call));
        }


        private const string SelectiveCallNotSynchronizedMsg = "Selective call target {0} is not synchronized";
        public static readonly int SelectiveCallNotSynchronizedError = NextErrorCode();

        internal static SyntaxError SelectiveCallNotSynchronized(object call)
        {
            return new SyntaxError(SelectiveCallNotSynchronizedError, string.Format(SelectiveCallNotSynchronizedMsg, call));
        }


        private const string AsynchronousCallNotAnEntryMsg = "Asynchronous call target {0} is not an entry/entry family";
        public static readonly int AsynchronousCallNotAnEntryError = NextErrorCode();

        internal static SyntaxError AsynchronousCallNotAnEntry(object call)
        {
            return new SyntaxError(AsynchronousCallNotAnEntryError, string.Format(AsynchronousCallNotAnEntryMsg, call));
        }


        private const string AsynchronousCallNotSynchronizedMsg = "Asynchronous call target {0} is not synchronized";
        public static readonly int AsynchronousCallNotSynchronizedError = NextErrorCode();

        internal static SyntaxError AsynchronousCallNotSynchronized(object call)
        {
            return new SyntaxError(AsynchronousCallNotSynchronizedError, string.Format(AsynchronousCallNotSynchronizedMsg, call));
        }


        private const string AcceptCallNotSynchronizedMsg = "Task {0}: Accept target {1} is not synchronized";
        public static readonly int AcceptCallNotSynchronizedError = NextErrorCode();

        internal static SyntaxError AcceptCallNotSynchronized(ITask task, object call)
        {
            return new SyntaxError(AcceptCallNotSynchronizedError, string.Format(AcceptCallNotSynchronizedMsg, task, call));
        }


        private const string IndexTypeMismatchMsg = "Task {0}: {1}'s accept body has the wrong index type";
        public static readonly int IndexTypeMismatchError = NextErrorCode();

        internal static SyntaxError IndexTypeMismatch(ITask task, SynchronizedMethod method)
        {
            return new SyntaxError(IndexTypeMismatchError, string.Format(IndexTypeMismatchMsg, task, method));
        }


        // TODO: a revoir
        private const string CallerEntryNotSynchronizedMsg = "Task {0}: Caller target is not a synchronized method";
        public static readonly int CallerEntryNotSynchronizedError = NextErrorCode();

        internal static SyntaxError CallerEntryNotSynchronized()
        {
            return new SyntaxError(CallerEntryNotSynchronizedError, string.Format(CallerEntryNotSynchronizedMsg, Task.CurrentRealTask));
        }

        // TODO: a revoir
        private const string ProtectedCallIsAFamilyMemberMsg = "Protected {0}: entry family member {1} cant be used in a call to Procedure/Function methods";
        public static readonly int ProtectedCallIsAFamilyMemberError = NextErrorCode();

        internal static SyntaxError ProtectedCallIsAFamilyMember(Protected prot, IExecutable entry)
        {
            return new SyntaxError(ProtectedCallIsAFamilyMemberError, string.Format(ProtectedCallIsAFamilyMemberMsg, prot, entry));
        }



        private const string RequeuedWhenNotInEntryMsg = "Synchronized Object {0}: Requeue can only be performed within an entry body";
        public static readonly int RequeuedWhenNotInEntryError = NextErrorCode();

        internal static SyntaxError RequeuedWhenNotInEntry(SynchronizedObject obj)
        {
            return new SyntaxError(RequeuedWhenNotInEntryError, string.Format(RequeuedWhenNotInEntryMsg, obj));
        }


        private const string RequeuedNotSynchronizedMsg = "Synchronized Object {0}: Requeue target is not a synchronized method";
        public static readonly int RequeuedNotSynchronizedError = NextErrorCode();

        internal static SyntaxError RequeuedNotSynchronized(SynchronizedObject obj)
        {
            return new SyntaxError(RequeuedNotSynchronizedError, string.Format(RequeuedNotSynchronizedMsg, obj));
        }


        private const string RequeuedIsNotAnEntryMsg = "Synchronized Object {0}: Requeue target {1} is not an entry";
        public static readonly int RequeuedIsNotAnEntryError = NextErrorCode();

        internal static SyntaxError RequeuedIsNotAnEntry(SynchronizedMethod target)
        {
            return new SyntaxError(RequeuedIsNotAnEntryError, string.Format(RequeuedIsNotAnEntryMsg, target.Owner, target));
        }


        private const string RequeueOnSameEntryMsg = "Synchronized Object {0}: Requeue on the same entry {1} is not allowed";
        public static readonly int RequeueOnSameEntryError = NextErrorCode();

        internal static SyntaxError RequeueOnSameEntry(SynchronizedMethod target)
        {
            return new SyntaxError(RequeueOnSameEntryError, string.Format(RequeueOnSameEntryMsg, target.Owner, target));
        }


        private const string SelfEntryCallMsg = "Task {0} : Can't call its own entry {1}";
        public static readonly int SelfEntryCallError = NextErrorCode();

        internal static SyntaxError SelfEntryCall(SynchronizedMethod called)
        {
            return new SyntaxError(SelfEntryCallError, string.Format(SelfEntryCallMsg, called.Owner, called));
        }


        private const string AcceptCallNotOwnedMsg = "Task {0} : Accept target {1} is not an entry of task";
        public static readonly int AcceptCallNotOwnedError = NextErrorCode();

        internal static SyntaxError AcceptCallNotOwned(SynchronizedMethod accept)
        {
            return new SyntaxError(AcceptCallNotOwnedError, string.Format(AcceptCallNotOwnedMsg, accept.Owner, accept));
        }


        private const string NotAMemberMsg = "Synchronized method {0} is not a member of Protected {1}";
        public static readonly int NotAMemberError = NextErrorCode();

        internal static SyntaxError NotAMember(Protected owner, SynchronizedMethod accept)
        {
            return new SyntaxError(NotAMemberError, string.Format(NotAMemberMsg, accept, owner));
        }


        private const string NotAnEntryMsg = "Synchronized method {0} is not an entry";
        public static readonly int NotAnEntryError = NextErrorCode();

        internal static SyntaxError NotAnEntry(SynchronizedMethod accept)
        {
            return new SyntaxError(NotAnEntryError, string.Format(NotAnEntryMsg, accept));
        }


        private const string ProtectedMethodCallNotInConstructorMsg = "Protected {0}: Calls to Entry/ReadOnlyOperation/ReadWriteOperation can only appear in the constructor";
        public static readonly int ProtectedMethodCallNotInConstructorError = NextErrorCode();

        internal static SyntaxError ProtectedMethodCallNotInConstructor(Protected prot)
        {
            return new SyntaxError(ProtectedMethodCallNotInConstructorError, string.Format(ProtectedMethodCallNotInConstructorMsg, prot));
        }


        private const string TaskCallNotInBodyMsg = "Task {0}: Select/Accept statements can only appear in the task Body";
        public static readonly int TaskCallNotInBodyError = NextErrorCode();

        internal static SyntaxError TaskCallNotInBody(Task task)
        {
            return new SyntaxError(TaskCallNotInBodyError, string.Format(TaskCallNotInBodyMsg, task));
        }


        private const string MultipleSelectiveCallsNotAllowedMsg = "Task {0}: Multiple selective calls not allowed";
        public static readonly int MultipleSelectiveCallsNotAllowedError = NextErrorCode();

        internal static SyntaxError MultipleSelectiveCallsNotAllowed(ITask task)
        {
            return new SyntaxError(MultipleSelectiveCallsNotAllowedError, string.Format(MultipleSelectiveCallsNotAllowedMsg, task));
        }


        private const string TaskCallNotFromBodyMsg = "Task {0}: Select/Accept statements can only appear in methods called from the task Body";
        public static readonly int TaskCallNotFromBodyError = NextErrorCode();

        internal static SyntaxError TaskCallNotFromBody(Task task)
        {
            return new SyntaxError(TaskCallNotFromBodyError, string.Format(TaskCallNotFromBodyMsg, task));
        }

        #endregion


        #region ProgramError error messages

        private const string ProtectedHasBeenDisposedMsg = "Protected {0}: object has been Disposed.";
        public static readonly int ProtectedHasBeenDisposedError = NextErrorCode();

        internal static ProgramError ProtectedHasBeenDisposed(Protected prot)
        {
            return new ProgramError(ProtectedHasBeenDisposedError, string.Format(ProtectedHasBeenDisposedMsg, prot));
        }


        private const string ProtectedIsBeingDisposedMsg = "Protected {0}: object has been Disposed.";
        public static readonly int ProtectedIsBeingDisposedError = NextErrorCode();

        internal static ProgramError ProtectedIsBeingDisposed(Protected prot)
        {
            return new ProgramError(ProtectedIsBeingDisposedError, string.Format(ProtectedIsBeingDisposedMsg, prot));
        }


        private const string PotentiallyBlockingOperationNotAllowedMsg = "Potentially blocking operation '{0}' not allowed";
        public static readonly int PotentiallyBlockingOperationNotAllowedError = NextErrorCode();

        internal static ProgramError PotentiallyBlockingOperationNotAllowed(string operation)
        {
            return new ProgramError(PotentiallyBlockingOperationNotAllowedError, string.Format(PotentiallyBlockingOperationNotAllowedMsg, operation));
        }


        private const string BarrierEvaluationThrewExceptionMsg = "Protected {0}: the evaluation of an entry barrier threw {1}.";
        public static readonly int BarrierEvaluationThrewExceptionError = NextErrorCode();

        internal static ProgramError BarrierEvaluationThrewException(Protected prot, Exception ex)
        {
            return new ProgramError(BarrierEvaluationThrewExceptionError, string.Format(BarrierEvaluationThrewExceptionMsg, prot, ex.GetType()));
        }


        private const string SelectHasNoOpenAlternativeMsg = "Task {0}: Select statement has no open alternative";
        public static readonly int SelectHasNoOpenAlternativeError = NextErrorCode();

        internal static ProgramError SelectHasNoOpenAlternative(ITask task)
        {
            return new ProgramError(SelectHasNoOpenAlternativeError, string.Format(SelectHasNoOpenAlternativeMsg, task));
        }


        private const string AsynchronousSelectNotAllowedMsg = "Execution of an asynchronous select within the execution of an abort-deferred operation not allowed (see RM 9.8 20)";
        public static readonly int AsynchronousSelectNotAllowedError = NextErrorCode();

        internal static ProgramError AsynchronousSelectNotAllowed()
        {
            return new ProgramError(AsynchronousSelectNotAllowedError, AsynchronousSelectNotAllowedMsg);
        }


        private const string NoMasterBlockMsg = "Use of tasking constructs can only appear within an Ada.Declare/Begin block";
        public static readonly int NoMasterBlockError = NextErrorCode();

        internal static ProgramError NoMasterBlock()
        {
            return new ProgramError(NoMasterBlockError, NoMasterBlockMsg);
        }


        private const string PriorityCeilingExceededMsg = "Task {0}: Priority {1} exceeds protected method {2} priority {3}";
        public static readonly int PriorityCeilingExceededError = NextErrorCode();

        internal static ProgramError PriorityCeilingExceeded(ITask task, SynchronizedMethod call)
        {
            return new ProgramError(PriorityCeilingExceededError, string.Format(PriorityCeilingExceededMsg, task, task.CurrentPriority, call, call.Owner.Priority));
        }

        #endregion


        #region TaskingError error messages

        private const string TaskIsTerminatedMsg = "{0} of {1} is invalid because Task {2} is terminated";
        public static readonly int TaskIsTerminatedError = NextErrorCode();

        private const string TaskIsAbnormalMsg = "{0} of {1} is invalid because Task {2} is abnormal";
        public static readonly int TaskIsAbnormalError = NextErrorCode();

        internal static TaskingError UnacceptableCall(MethodCall call)
        {
            return ((Task)call.Target.Owner).TaskStatus == TaskStatus.Terminated ?
                new TaskingError(TaskIsTerminatedError, string.Format(TaskIsTerminatedMsg, "Call", call, call.Target.Owner)) :
                new TaskingError(TaskIsAbnormalError, string.Format(TaskIsAbnormalMsg, "Call", call, call.Target.Owner));
        }


        internal static TaskingError UnacceptableRequeue(MethodCall call, SynchronizedObject task)
        {
            return ((Task)call.Target.Owner).TaskStatus == TaskStatus.Terminated ?
                new TaskingError(TaskIsTerminatedError, string.Format(TaskIsTerminatedMsg, "Requeue", call, task)) :
                new TaskingError(TaskIsAbnormalError, string.Format(TaskIsAbnormalMsg, "Requeue", call, task));
        }


        private const string ActivationFailedMsg = "Activation of some of the sub-tasks failed (see RM 9.2 5):{0}";
        public static readonly int ActivationFailedError = NextErrorCode();

        internal static TaskingError ActivationFailed(string message)
        {
            return new TaskingError(ActivationFailedError, string.Format(ActivationFailedMsg, message));
        }


        private const string AcceptAbortedMsg = "Task {0} aborted while accepting call {1} from {2}";
        public static readonly int AcceptAbortedError = NextErrorCode();

        internal static TaskingError AcceptAborted(MethodCall call)
        {
            return new TaskingError(AcceptAbortedError, string.Format(AcceptAbortedMsg, Task.CurrentTask, call, call.Thread));
        }

        #endregion

    }

}
